package com.washmadam.service.common.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy/MM/dd",
            "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyyMMddHHmmss", "yyyy.MM.dd", "yyyy.MM"};
    /**
     * Default time format : yyyy-MM-dd HH:mm:ss
     */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String EN_DATE_TIME_FORMAT = "yyyyMMddHHmmss";

    public static final String EN_DATE_FORMAT = "yyyy-MM-dd HH:mm";

    public static final String TIME_SECOND_FORMAT = "HH:mm:ss";

    public static final String TIME_SECOND_FORMAT_EN = "HHmmss";

    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";

    public static final String TIME_FORMAT = "HH:mm";

    public static final String UTC_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    public static final String DATE_FORMAT_V2 = "yyyy.MM.dd";

    public static final String DATE_FORMAT_EN = "yyyyMMdd";

    public static final String DATE_FORMAT_CN = "yyyy年MM月dd日";

    public static final String DATE_TIME_FORMAT_CN = "yyyy年MM月dd日 HH:mm";

    public static final String MONTH_FORMAT_CN = "MM月dd日";

    public static final String MONTH_FORMAT = "yyyy-MM";

    public static final String MONTH_FORMAT_EN = "yyyyMM";

    public static final String DAY_FORMAT = "dd";

    public static final String YEAR_FORMAT = "yyyy";

    public static String getDate() {
        return getDate(DATE_FORMAT);
    }

    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String getDate(String pattern) {
        return DateFormatUtils.format(new Date(), pattern);
    }

    /**
     * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(Date date, Object... pattern) {
        String formatDate = null;
        if (date == null) {
            return formatDate;
        }
        if (pattern != null && pattern.length > 0) {
            formatDate = DateFormatUtils.format(date, pattern[0].toString());
        } else {
            formatDate = DateFormatUtils.format(date, DEFAULT_DATE_TIME_FORMAT);
        }
        return formatDate;
    }

    /**
     * 得到当前时间字符串 格式（HH:mm:ss）
     */
    public static String getTime() {
        return formatDate(new Date(), TIME_SECOND_FORMAT);
    }

    /**
     * 得到当前日期和时间字符串 格式（yyyy-MM-dd HH:mm:ss）
     */
    public static String getDateTime() {
        return formatDate(new Date(), DEFAULT_DATE_TIME_FORMAT);
    }

    /**
     * 得到当前年份字符串 格式（yyyy）
     */
    public static String getYear() {
        return formatDate(new Date(), "yyyy");
    }

    /**
     * 得到当前月份字符串 格式（MM）
     */
    public static String getMonth() {
        return formatDate(new Date(), "MM");
    }

    /**
     * 得到当天字符串 格式（dd）
     */
    public static String getDay() {
        return formatDate(new Date(), "dd");
    }

    /**
     * 得到当前星期字符串 格式（E）星期几
     */
    public static String getWeek() {
        return formatDate(new Date(), "E");
    }

    /**
     * 得到当前时间字符串
     */
    public static String getHour() {
        return formatDate(new Date(), "HH");
    }

    /**
     * 日期型字符串转化为日期 格式 { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm" }
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public static Date getCurrentDate() {
        try {
            return parseDate(getCurrentDateString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }
    public static String getCurrentDateString() {
        try {
            return getDate(DATE_FORMAT);
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 获取过去的天数
     *
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 根据给定的日期来设置这一天的起始时间
     *
     * @param date
     * @return
     */
    public static Date getBeginDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }
    public static void main(String[] args) {
		System.out.println(getBeginDate(new Date()));
	}
    /**
     * 根据给定的日期来设置这一天的结束时间
     *
     * @param date
     * @return
     */
    public static Date getEndDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    /**
     * 获取给定日期的前几天或后几天
     *
     * @param date
     * @param days 为正则相加，为负则相减
     * @return
     */
    public static Date addSomeDays(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return new Date(calendar.getTime().getTime());
    }

    /**
     * 获取给定日期的前几月或后几月
     *
     * @param date
     * @param months 为正则相加，为负则相减
     * @return
     */
    public static Date addSomeMonths(Date date, int months) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, months);
        return new Date(calendar.getTime().getTime());
    }

    /**
     * 获取某一个月共有多少天
     *
     * @param year
     * @param month 范围为 0-11
     * @return
     */
    public static int getDaysOfMonth(int year, int month) {
        return new GregorianCalendar(year, month, 1).getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当前月共有多少天
     *
     * @param date 范围为 0-11
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        int year = getYear(date);
        int month = getMonth(date);
        return getDaysOfMonth(year, month);
    }

    /**
     * 根据年、月、日构造 date
     *
     * @param year
     * @param month month 的范围为 0-11
     * @param day
     * @return
     */
    public static Date getDate(int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(year, month, day);
        return c.getTime();
    }

    public static int getYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    public static int getMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH);
    }

    public static int getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 计算两个日期之间相差的月数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int monthBetween(Date smdate, Date bdate) throws ParseException {
        int result = 0;
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));

        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(smdate);
        c2.setTime(bdate);

        result = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);

        return result == 0 ? 1 : Math.abs(result);
    }

    /**
     * 计算两个日期之间相差的年
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差年数
     * @throws ParseException
     */
    public static int yearBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(YEAR_FORMAT);
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));

        Calendar calBegin = Calendar.getInstance(); //获取日历实例
        Calendar calEnd = Calendar.getInstance();
        calBegin.setTime(smdate); //字符串按照指定格式转化为日期
        calEnd.setTime(bdate);
        return calEnd.get(Calendar.YEAR) - calBegin.get(Calendar.YEAR);
    }

    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        String strDate1 = DateFormatUtils.format(new Date(date1.getTime()), DATE_FORMAT);
        String strDate2 = DateFormatUtils.format(new Date(date2.getTime()), DATE_FORMAT);
        return strDate1.equals(strDate2);
    }

    public static String getStrDate(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(new Date(date.getTime()), DATE_FORMAT);
    }

    /**
     * formate to yyyy-MM-dd Date
     *
     * @param dateText
     * @return
     */
    public static Date dateStrToDate(String dateText) {
        return dateStrToDate(dateText, DATE_FORMAT);
    }

    /**
     * formate to pattern Date
     *
     * @param dateText
     * @param pattern
     * @return
     */
    public static Date dateStrToDate(String dateText, String pattern) {
        DateFormat dateFormat = createDateFormat(pattern);
        try {
            return dateFormat.parse(dateText);
        } catch (ParseException e) {
            throw new IllegalStateException("Parse date from [" + dateText + "," + pattern + "] failed", e);
        }
    }

    /**
     * DateFormat
     *
     * @param pattern
     * @return
     */
    private static DateFormat createDateFormat(String pattern) {
        return new SimpleDateFormat(pattern, Locale.SIMPLIFIED_CHINESE);
    }

    static int[] DAYS = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /**
     * @param date yyyyMMddHHmmss
     * @return
     */
    public static boolean isValidDate(String date) {
        try {
            int year = Integer.parseInt(date.substring(0, 4));
            if (year <= 0)
                return false;
            int month = Integer.parseInt(date.substring(4, 6));
            if (month <= 0 || month > 12)
                return false;
            int day = Integer.parseInt(date.substring(6, 8));
            if (day <= 0 || day > DAYS[month])
                return false;
            if (month == 2 && day == 29 && !isGregorianLeapYear(year)) {
                return false;
            }
            int hour = Integer.parseInt(date.substring(8, 10));
            if (hour < 0 || hour > 23)
                return false;
            int minute = Integer.parseInt(date.substring(10, 12));
            if (minute < 0 || minute > 59)
                return false;
            int second = Integer.parseInt(date.substring(12, 14));
            if (second < 0 || second > 59)
                return false;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static final boolean isGregorianLeapYear(int year) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }

    public static Date addMinute(Date date, int minutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, minutes);
        return cal.getTime();
    }
}
